
Public Class DataGridComboBoxColumn
   Inherits DataGridTextBoxColumn

   Private mComboBox As DataGridComboBox
   Private mCurrencyManager As CurrencyManager
   Private mintRowNumber As Integer
   Private mblnEdicion As Boolean

   Public Sub New(ByVal dataSource As DataView, ByVal displayMember As String, ByVal valueMember As String)

      mCurrencyManager = Nothing
      mblnEdicion = False

      mComboBox = New DataGridComboBox

      mComboBox.DropDownStyle = ComboBoxStyle.DropDownList
      mComboBox.Visible = False

      mComboBox.DataSource = dataSource
      mComboBox.DisplayMember = displayMember
      mComboBox.ValueMember = valueMember

      AddHandler mComboBox.Leave, AddressOf mComboBox_Leave
      AddHandler mComboBox.SelectionChangeCommitted, AddressOf mComboBox_SelectionChangeCommitted

   End Sub

   Public ReadOnly Property ComboBox() As DataGridComboBox
      Get
         Return mComboBox
      End Get
   End Property

   Private Sub mComboBox_Leave(ByVal sender As Object, ByVal e As EventArgs)

      If mblnEdicion Then

         mblnEdicion = False

         SetColumnValueAtRow(mCurrencyManager, mintRowNumber, mComboBox.Text)

         Invalidate()

      End If

      mComboBox.Visible = False

      AddHandler DataGridTableStyle.DataGrid.Scroll, AddressOf DataGrid_Scroll

   End Sub

   Private Sub DataGrid_Scroll(ByVal sender As Object, ByVal e As EventArgs)

      If mComboBox.Visible Then
         mComboBox.Visible = False
      End If

   End Sub

   Private Sub mComboBox_SelectionChangeCommitted(ByVal sender As Object, ByVal e As EventArgs)

      mblnEdicion = True

      MyBase.ColumnStartedEditing(CType(sender, Control))

   End Sub

   Protected Overrides Function GetMinimumHeight() As Integer

      Return mComboBox.PreferredHeight

   End Function

   Protected Overrides Sub SetDataGridInColumn(ByVal value As DataGrid)

      MyBase.SetDataGridInColumn(value)

      mComboBox.Parent = CType(value, Control)

   End Sub

   Protected Overrides Sub ConcedeFocus()

      MyBase.ConcedeFocus()

      mComboBox.Visible = False

   End Sub

   Protected Overloads Overrides Sub Edit(ByVal source As CurrencyManager, ByVal rowNum As Integer, ByVal bounds As Rectangle, ByVal [readOnly] As Boolean, ByVal instantText As String, ByVal cellIsVisible As Boolean)

      MyBase.Edit(source, rowNum, bounds, [readOnly], instantText, cellIsVisible)

      Me.TextBox.Visible = False

      mintRowNumber = rowNum
      mCurrencyManager = source

      mComboBox.Bounds = bounds
      mComboBox.RightToLeft = Me.DataGridTableStyle.DataGrid.RightToLeft

      If cellIsVisible AndAlso Not [readOnly] Then
         mComboBox.Visible = True
         mComboBox.BringToFront()
         mComboBox.Focus()
      End If

      mComboBox.SelectedIndex = mComboBox.FindStringExact(Me.TextBox.Text)

      AddHandler DataGridTableStyle.DataGrid.Scroll, AddressOf DataGrid_Scroll

   End Sub

   Protected Overrides Function Commit(ByVal dataSource As CurrencyManager, ByVal rowNum As Integer) As Boolean

      If mblnEdicion Then
         mblnEdicion = False
         SetColumnValueAtRow(dataSource, rowNum, mComboBox.Text)
      End If

      Return True

   End Function

   Protected Overrides Sub SetColumnValueAtRow(ByVal source As CurrencyManager, ByVal rowNum As Integer, ByVal value As Object)

      MyBase.SetColumnValueAtRow(source, rowNum, mComboBox.FindValueMember(value))

   End Sub

   Protected Overrides Function GetColumnValueAtRow(ByVal source As CurrencyManager, ByVal rowNum As Integer) As Object

      Dim val As Object = MyBase.GetColumnValueAtRow(source, rowNum)

      Return mComboBox.FindDisplayMember(val)

   End Function

   Protected Overrides Sub Abort(ByVal rowNum As Integer)

   End Sub

   Protected Overrides Function GetPreferredHeight(ByVal g As System.Drawing.Graphics, ByVal value As Object) As Integer

   End Function

   Protected Overrides Function GetPreferredSize(ByVal g As System.Drawing.Graphics, ByVal value As Object) As System.Drawing.Size

   End Function

   Protected Overloads Overrides Sub Paint(ByVal g As System.Drawing.Graphics, ByVal bounds As System.Drawing.Rectangle, ByVal source As System.Windows.Forms.CurrencyManager, ByVal rowNum As Integer)

   End Sub

   Protected Overloads Overrides Sub Paint(ByVal g As System.Drawing.Graphics, ByVal bounds As System.Drawing.Rectangle, ByVal source As System.Windows.Forms.CurrencyManager, ByVal rowNum As Integer, ByVal alignToRight As Boolean)

   End Sub

End Class

Public Class DataGridComboBox
   Inherits System.Windows.Forms.ComboBox
   Private WM_KEYUP As Integer = &H101

   Protected Overrides Sub WndProc(ByRef theMessage As System.Windows.Forms.Message)

      If theMessage.Msg = WM_KEYUP Then
         Return
      End If

      MyBase.WndProc(theMessage)

   End Sub

   Public Function FindValueMember(ByVal display As Object) As Object
      Dim dv As DataView = CType(DataSource, DataView)
      Dim rowCount As Integer = dv.Count

      Dim disp As Object
      Dim i As Integer
      For i = 0 To rowCount - 1
         disp = dv(i)(DisplayMember)

         If display.Equals(disp) Then
            Return dv(i)(ValueMember)
         End If
      Next i

      Return DBNull.Value

   End Function

   Public Function FindDisplayMember(ByVal value As Object) As Object
      Dim dv As DataView = CType(DataSource, DataView)
      Dim rowCount As Integer = dv.Count

      Dim val As Object
      Dim i As Integer

      For i = 0 To rowCount - 1
         val = dv(i)(ValueMember)

         If value.Equals(val) Then
            Return dv(i)(DisplayMember)
         End If

      Next i

      Return DBNull.Value

   End Function

End Class